/**
 * @file hitls_client_example.c
 * @brief HiTLS客户端使用示例
 * 
 * 本示例展示如何使用altcp_tls_hitls替代mbedtls实现TLS客户端
 * 主要演示与mbedtls版本的使用差异
 */

#include "lwip/opt.h"

#if LWIP_ALTCP && LWIP_ALTCP_TLS_HITLS

#include "lwip/apps/altcp_tls_hitls.h"
#include "lwip/altcp_tcp.h"
#include "lwip/dns.h"
#include "lwip/mem.h"
#include "lwip/debug.h"

#include <string.h>

/* 示例服务器信息 */
#define EXAMPLE_SERVER_NAME     "192.168.100.2"
#define EXAMPLE_SERVER_PORT     443
#define EXAMPLE_REQUEST         "GET / HTTP/1.1\r\nHost: " EXAMPLE_SERVER_NAME "\r\nConnection: close\r\n\r\n"

/* CA证书示例（实际使用时替换为真实证书） */
static const char ca_cert_pem[] = 
"-----BEGIN CERTIFICATE-----\r\n"
"... CA证书内容 ...\r\n"
"-----END CERTIFICATE-----\r\n";

/* 连接状态结构 */
typedef struct {
    struct altcp_pcb *pcb;
    struct altcp_tls_config *tls_config;
    int connected;
    int data_sent;
} tls_client_t;

/**
 * TLS连接关闭回调
 */
static void
tls_client_close_conn(tls_client_t *client)
{
    if (client->pcb) {
        altcp_arg(client->pcb, NULL);
        altcp_recv(client->pcb, NULL);
        altcp_sent(client->pcb, NULL);
        altcp_poll(client->pcb, NULL, 0);
        altcp_err(client->pcb, NULL);
        altcp_close(client->pcb);
        client->pcb = NULL;
    }
    
    if (client->tls_config) {
        altcp_tls_free_config(client->tls_config);
        client->tls_config = NULL;
    }
}

/**
 * 接收回调函数
 */
static err_t
tls_client_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err)
{
    tls_client_t *client = (tls_client_t *)arg;
    
    if (err != ERR_OK || p == NULL) {
        if (p) {
            pbuf_free(p);
        }
        printf("TLS connection closed or error: %d\n", err);
        tls_client_close_conn(client);
        return ERR_OK;
    }
    
    /* 处理接收到的数据 */
    printf("Received %d bytes:\n", p->tot_len);
    
    /* 打印接收到的数据（HTTP响应） */
    struct pbuf *q;
    for (q = p; q != NULL; q = q->next) {
        printf("%.*s", q->len, (char *)q->payload);
    }
    
    /* 确认接收 */
    altcp_recved(pcb, p->tot_len);
    pbuf_free(p);
    
    /* 接收完成后关闭连接 */
    tls_client_close_conn(client);
    
    return ERR_OK;
}

/**
 * 发送回调函数
 */
static err_t
tls_client_sent(void *arg, struct altcp_pcb *pcb, u16_t len)
{
    tls_client_t *client = (tls_client_t *)arg;
    
    printf("Sent %d bytes\n", len);
    client->data_sent = 1;
    
    return ERR_OK;
}

/**
 * 连接成功回调函数
 */
static err_t
tls_client_connected(void *arg, struct altcp_pcb *pcb, err_t err)
{
    tls_client_t *client = (tls_client_t *)arg;
    
    if (err != ERR_OK) {
        printf("TLS connection failed: %d\n", err);
        tls_client_close_conn(client);
        return err;
    }
    
    printf("TLS connection established!\n");
    client->connected = 1;
    
    /* 发送HTTP请求 */
    err = altcp_write(pcb, EXAMPLE_REQUEST, strlen(EXAMPLE_REQUEST), TCP_WRITE_FLAG_COPY);
    if (err != ERR_OK) {
        printf("Failed to send HTTP request: %d\n", err);
        tls_client_close_conn(client);
        return err;
    }
    
    return ERR_OK;
}

/**
 * 错误回调函数
 */
static void
tls_client_err(void *arg, err_t err)
{
    tls_client_t *client = (tls_client_t *)arg;
    
    printf("TLS client error: %d\n", err);
    
    /* 错误时清理资源 */
    client->pcb = NULL; /* PCB已被lwip释放 */
    if (client->tls_config) {
        altcp_tls_free_config(client->tls_config);
        client->tls_config = NULL;
    }
}

/**
 * DNS解析回调函数
 */
static void
dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
{
    tls_client_t *client = (tls_client_t *)callback_arg;
    err_t err;
    
    if (ipaddr == NULL) {
        printf("DNS resolution failed for %s\n", name);
        tls_client_close_conn(client);
        return;
    }
    
    printf("DNS resolved %s to %s\n", name, ipaddr_ntoa(ipaddr));
    
    /* 创建TLS配置 - 关键差异点：使用HiTLS接口 */
    client->tls_config = altcp_tls_create_config_client(
        (const u8_t *)ca_cert_pem, 
        strlen(ca_cert_pem)
#ifdef LWIP_ALTCP_HITLS_AUTH_MODE
        , 1  /* 启用服务器证书验证 */
#endif
    );
    
    if (!client->tls_config) {
        printf("Failed to create TLS config\n");
        return;
    }
    
    /* 创建TLS连接 */
    client->pcb = altcp_tls_new(client->tls_config, IPADDR_TYPE_V4);
    if (!client->pcb) {
        printf("Failed to create TLS PCB\n");
        altcp_tls_free_config(client->tls_config);
        client->tls_config = NULL;
        return;
    }
    
    /* 设置回调函数 */
    altcp_arg(client->pcb, client);
    altcp_recv(client->pcb, tls_client_recv);
    altcp_sent(client->pcb, tls_client_sent);
    altcp_err(client->pcb, tls_client_err);
    
    /* 发起连接 */
    err = altcp_connect(client->pcb, ipaddr, EXAMPLE_SERVER_PORT, tls_client_connected);
    if (err != ERR_OK) {
        printf("Failed to connect: %d\n", err);
        tls_client_close_conn(client);
        return;
    }
    
    printf("Connecting to %s:%d...\n", ipaddr_ntoa(ipaddr), EXAMPLE_SERVER_PORT);
}

/**
 * 启动TLS客户端连接
 */
void
hitls_client_example_start(void)
{
    static tls_client_t client;
    ip_addr_t server_ip;
    err_t err;
    
    memset(&client, 0, sizeof(client));
    
    printf("Starting HiTLS client example...\n");
    
    /* 尝试直接解析IP地址 */
    if (ipaddr_aton(EXAMPLE_SERVER_NAME, &server_ip)) {
        /* 已经是IP地址，直接连接 */
        dns_found_cb(EXAMPLE_SERVER_NAME, &server_ip, &client);
    } else {
        /* 需要DNS解析 */
        err = dns_gethostbyname(EXAMPLE_SERVER_NAME, &server_ip, dns_found_cb, &client);
        if (err == ERR_OK) {
            /* DNS缓存中已有结果 */
            dns_found_cb(EXAMPLE_SERVER_NAME, &server_ip, &client);
        } else if (err != ERR_INPROGRESS) {
            printf("DNS query failed: %d\n", err);
        } else {
            printf("DNS query in progress...\n");
        }
    }
}

/**
 * 国密算法配置示例
 * 展示如何配置国密密码套件和算法
 */
struct altcp_tls_config *
hitls_create_gm_config_example(void)
{
    struct altcp_tls_config *config;
    int32_t ret;
    
    /* 创建基础TLS配置 */
    config = altcp_tls_create_config_client(NULL, 0
#ifdef LWIP_ALTCP_HITLS_AUTH_MODE
        , 0  /* 暂时不验证证书，用于测试 */
#endif
    );
    
    if (!config) {
        return NULL;
    }
    
    /* 配置国密密码套件（示例） */
    /* 注意：具体的HiTLS API可能与此处示例有所不同，请参考HiTLS文档 */
    
    /* 设置TLCP版本 */
    ret = HITLS_CFG_SetVersion(config->hitls_config, HITLS_VERSION_TLCP11, HITLS_VERSION_TLCP11);
    if (ret != HITLS_SUCCESS) {
        printf("设置TLCP版本失败: %d\n", ret);
        altcp_tls_free_config(config);
        return NULL;
    }
    
    /* 设置国密密码套件 */
    const uint16_t gm_cipher_suites[] = {
        /* 这里应该是实际的国密密码套件ID，请参考HiTLS文档 */
        /* HITLS_ECDHE_SM2_WITH_SM4_SM3,
           HITLS_ECC_SM2_WITH_SM4_SM3, */
        0  /* 结束标记 */
    };
    
    /* 注意：实际的HiTLS密码套件配置API可能不同 */
    /*
    ret = HITLS_CFG_SetCipherSuites(config->hitls_config, gm_cipher_suites, sizeof(gm_cipher_suites)/sizeof(gm_cipher_suites[0]) - 1);
    if (ret != HITLS_SUCCESS) {
        printf("设置国密密码套件失败: %d\n", ret);
        altcp_tls_free_config(config);
        return NULL;
    }
    */
    
    printf("国密TLS配置创建成功\n");
    return config;
}

#endif /* LWIP_ALTCP && LWIP_ALTCP_TLS_HITLS */

/**
 * 使用说明：
 * 
 * 1. 编译时确保包含HiTLS库和头文件
 * 2. 在lwipopts.h中启用相关配置：
 *    - LWIP_ALTCP=1
 *    - LWIP_ALTCP_TLS=1  
 *    - LWIP_ALTCP_TLS_HITLS=1
 *    - LWIP_ALTCP_TLS_MBEDTLS=0
 * 
 * 3. 调用hitls_client_example_start()启动客户端
 * 
 * 4. 与mbedtls版本的主要差异：
 *    - 配置创建：使用altcp_tls_create_config_client替代mbedtls版本
 *    - 支持认证模式和CRL配置
 *    - 支持国密算法和TLCP协议
 *    - 错误码和配置参数有所不同
 */ 